﻿using System;
using System.Collections.Generic;
using System.Linq;
using HK.Core.Common.Data;

namespace HK.Core.Utils
{
    
    /// <summary>
    /// 工具类 : 数据
    /// </summary>
    public static class UtilsArray
    {
        /// <summary>
        /// 比较列表
        /// </summary>
        /// <param name="iCurList">当前列表</param>
        /// <param name="iDstList">目标列表</param>
        /// <param name="iCompare">比较回调</param>
        /// <param name="iStrict">严格比较标志位(true:顺序不同也会视为不同; false:列表中顺序将会被忽略;)</param>
        /// <typeparam name="TValue">值类型</typeparam>
        /// <returns>true:不同; false:相同;</returns>
        public static bool Diff<TValue>(IReadOnlyList<TValue> iCurList, IReadOnlyList<TValue> iDstList,
            Func<TValue, TValue, bool> iCompare, bool iStrict = true)
            where TValue : struct
        {
            if (null == iCurList && null == iDstList) return true;
            if (null == iCurList) return false;
            if (null == iDstList) return false;
            
            if (0 == iCurList.Count && 0 == iDstList.Count) return false;
            if (iCurList.Count != iDstList.Count) return true;

            var curList = iCurList;
            var dstList = iDstList;
            if (!iStrict)
            {
                curList = curList.OrderBy(iO => iO).ToList();
                dstList = dstList.OrderBy(iO => iO).ToList();
            }
            
            var count = curList.Count;
            var flg = true;

            for (var idx = 0; idx < count; ++idx)
            {
                var curElement = curList[idx];
                var dstElement = dstList[idx];
                
                // 比较
                flg = iCompare(curElement, dstElement);
                if(!flg) break;
            }
            
            return flg;
        }

        /// <summary>
        /// 比较列表
        /// </summary>
        /// <param name="iCurList">当前列表</param>
        /// <param name="iDstList">目标列表</param>
        /// <param name="iStrict">严格比较标志位(true:列表中大小写，顺序不同也会视为不同; false:列表中顺序以及大小写，将会被忽略;)</param>
        /// <returns>true:不同; false:相同;</returns>
        public static bool Diff(IReadOnlyList<string> iCurList, IReadOnlyList<string> iDstList, bool iStrict = true)
        {
            if (null == iCurList && null == iDstList) return true;
            if (null == iCurList) return false;
            if (null == iDstList) return false;
            
            if (0 == iCurList.Count && 0 == iDstList.Count) return false;
            if (iCurList.Count != iDstList.Count) return true;

            var count = iCurList.Count;
            var flg = true;

            var curList = iCurList;
            var dstList = iDstList;
            if (!iStrict)
            {
                curList = curList.OrderBy(iO => iO).ToList();
                dstList = dstList.OrderBy(iO => iO).ToList();
            }
            
            for (var idx = 0; idx < count; ++idx)
            {
                var curElement = curList[idx];
                var dstElement = dstList[idx];
                if (iStrict)
                {
                    curElement = curElement.ToLower();
                    dstElement = dstElement.ToLower();
                }
                
                // Diff比较
                flg = !UtilsString.Diff(curElement, dstElement);
                if(!flg) break;
            }
            
            return flg;
        }
        
        /// <summary>
        /// 比较列表
        /// </summary>
        /// <param name="iCurList">当前列表</param>
        /// <param name="iDstList">目标列表</param>
        /// <param name="iStrict">严格比较标志位(true:顺序不同也会视为不同; false:列表中顺序将会被忽略;)</param>
        /// <typeparam name="TElement">Element类型</typeparam>
        /// <returns>true:不同; false:相同;</returns>
        public static bool Diff<TElement>(IReadOnlyList<TElement> iCurList, IReadOnlyList<TElement> iDstList, bool iStrict = true)
            where TElement : JsonData, IEquatable<TElement>
        {
            if (null == iCurList && null == iDstList) return true;
            if (null == iCurList) return false;
            if (null == iDstList) return false;
            
            if (0 == iCurList.Count && 0 == iDstList.Count) return false;
            if (iCurList.Count != iDstList.Count) return true;

            var curList = iCurList;
            var dstList = iDstList;
            if (!iStrict)
            {
                curList = curList.OrderBy(iO => iO).ToList();
                dstList = dstList.OrderBy(iO => iO).ToList();
            }
            
            var count = curList.Count;
            var flg = true;

            for (var idx = 0; idx < count; ++idx)
            {
                var curElement = curList[idx];
                var dstElement = dstList[idx];
                flg = CompareElement(curElement, dstElement);
                if(!flg) break;
            }
            
            return flg;
        }

        /// <summary>
        /// 比较列表元素
        /// </summary>
        /// <param name="iCurElement">当前Element</param>
        /// <param name="iDstElement">目标Element</param>
        /// <typeparam name="TElement">Element类型</typeparam>
        /// <returns>true:相同; false:不同;</returns>
        private static bool CompareElement<TElement>(TElement iCurElement, TElement iDstElement)
            where TElement : JsonData, IEquatable<TElement>
        {
            if (null == iCurElement && null == iDstElement) return true;
            if (null == iCurElement) return false;
            if (null == iDstElement) return false;

            return iCurElement.Equals(iDstElement);
        }
    }
}